// CallsTable.cpp : CallsTable is used to keep track of all the calls made in each procedures.
// Author: Achyut P Balaji
//

#include"CallsTable.h"

/*Description: Private Constructor if class CallsTable.*/
CallsTable::CallsTable() {
}

CallsTable* CallsTable::obj = NULL;

/*Description: This function is used to get the object of the class CallsTable.
Implements the Singleton Design Pattern and prevents decleration of anymore objects of this class. */
CallsTable* CallsTable::getInstance(){
	if(!obj) 
		obj = new CallsTable;
	return obj;
}

/*Description: This function is used to reinitialise the object of the class CallsTable.
Implements the Singleton Design Pattern and prevents decleration of anymore objects of this class. */
CallsTable* CallsTable::getFirstInstance(){
	obj = new CallsTable;
	return obj;
}

BOOLEAN CallsTable::insertCall(PROC_INDEX p1, PROC_INDEX p2) {
	if(callsList.at(p1).at(0) == -1) {
		callsList.at(p1).pop_back();
		callsList.at(p1).push_back(p2);
		return true;
	}
	bool temp = true;
	for(unsigned int i=0;i < callsList.at(p1).size();i++) {
		if(callsList.at(p1).at(i) == p2) 
			temp = false;
	}
	if (temp == true)
		callsList.at(p1).push_back(p2);
	return true;
}

BOOLEAN CallsTable::insertCallStar(PROC_INDEX p1,PROC_LIST p) {
	if(callsStarList.at(p1).at(0) == -1) {
		callsStarList.at(p1).pop_back();
		for(unsigned int i=0;i<p.size();i++) {
			callsStarList.at(p1).push_back(p.at(i));
		}
		return true;
	}
	for(unsigned int j=0;j<p.size();j++) {
		bool temp = true;
		for(unsigned int i=0;i < callsStarList.at(p1).size();i++) {
			if(callsStarList.at(p1).at(i) == p.at(j)) 
				temp = false;
		}
		if (temp == true)
			callsStarList.at(p1).push_back(p.at(j));
		//return true;
	}
	return true;
}

void CallsTable::initialise(int size) {
	vector<PROC_INDEX> temp;
	temp.push_back(-1);
	for(int i=0;i<size;i++) {
		callsList.push_back(temp);
		callsStarList.push_back(temp);
	}
}

void CallsTable::emptyTempVector() {
	int temp = tempVector.size();
	for(int i=0;i<temp;i++) {
		tempVector.pop_back();
	}
}

BOOLEAN CallsTable::isCalled(PROC_INDEX p1, PROC_INDEX p2) {
	for(unsigned int i =0;i<callsList.at(p1).size();i++) {
		if(callsList.at(p1).at(i) == p2)
			return true;
	}
	return false;
}

BOOLEAN CallsTable::isCalledStar(PROC_INDEX p1, PROC_INDEX p2) {
	for(unsigned int i =0;i<callsStarList.at(p1).size();i++) {
		if(callsStarList.at(p1).at(i) == p2)
			return true;
	}
	return false;
}

PROC_LIST* CallsTable::getProcCalled(PROC_INDEX ind) {
	unsigned int p = ind;
	emptyTempVector();
	if(p<callsList.size()) {
		return &callsList.at(p);
	}
	else {
		tempVector.push_back(-1);
		return &tempVector;
	}
}

PROC_LIST* CallsTable::getCallsStar(PROC_INDEX ind) {
	unsigned int p = ind;
	emptyTempVector();
	if(p<callsStarList.size()) {
		return &callsStarList.at(p);
	}
	else {
		tempVector.push_back(-1);
		return &tempVector;
	}
}

PROC_LIST* CallsTable::getList(PROC_INDEX ind) {
	unsigned int p = ind;
	emptyTempVector();
	if(p<=callsList.size()){
		unsigned int j=0;
		tempVector.push_back(p);
		if(callsList.at(p).at(0) == -1) {
			return &tempVector;
		}
		while(j<tempVector.size()){
			if(callsList.at(tempVector.at(j)).at(0) != -1) {
				for(unsigned int i=0;i<callsList.at(tempVector.at(j)).size();i++) {
					bool bool1 = false;
					for(unsigned int k=0;k<tempVector.size();k++) {
						if(callsList.at(tempVector.at(j)).at(i) == tempVector.at(k)) {
							bool1 = true;
						}
					}
					if(bool1 == false) {
						tempVector.push_back(callsList.at(tempVector.at(j)).at(i));
					}
				}
			}
			j++;
		}

		return &tempVector;
	}
	else {
		tempVector.push_back(-1);
		return &tempVector;
	}
}

PROC_LIST* CallsTable::getProcList(PROC_INDEX ind) {
	unsigned int p = ind;
	emptyTempVector();
	if(p<=callsList.size()){
		unsigned int j=0;
		if(callsList.at(p).at(0) == -1) {
			return &tempVector;
		}
		bool tempo = true;
		while(j<tempVector.size() || tempo==true){
			if(tempo==true){
				for(unsigned int i=0;i<callsList.at(p).size();i++) {
					bool bool1 = false;
					for(unsigned int k=0;k<tempVector.size();k++) {
						if(callsList.at(p).at(i) == tempVector.at(k)) {
							bool1 = true;
						}
					}
					if(bool1 == false) {
						tempVector.push_back(callsList.at(p).at(i));
					}
				}
				tempo = false;
			}
			else{
				if(callsList.at(tempVector.at(j)).at(0) != -1) {
					for(unsigned int i=0;i<callsList.at(tempVector.at(j)).size();i++) {
						bool bool1 = false;
						for(unsigned int k=0;k<tempVector.size();k++) {
							if(callsList.at(tempVector.at(j)).at(i) == tempVector.at(k)) {
								bool1 = true;
							}
						}
						if(bool1 == false) {
							tempVector.push_back(callsList.at(tempVector.at(j)).at(i));
						}
					}
				}
				j++;
			}
		}

		return &tempVector;
	}
	else {
		tempVector.push_back(-1);
		return &tempVector;
	}
}